準備技術:
什麼是Thread?在計算機架構中,CPU載入OS指派的程式執行,OS會開Process處理進行事情,Process只是一個抽象,會有PID編號,每個Process內一定有一個Thread實際去執行這個程式,一個Process內可以有多個Thread共享Process被分配的記憶體來做事,Thread彼此之間可能有資訊交換,因為資料完整性與安全,要考慮同步機制。
通常一個Servlet是由一個thread負責,可以想見若是多個Servlet之間的資料傳遞多危險。
先看一個例子,計數器,很簡單的數數字,這個在Thread之間傳遞數字會有問題,你要數字1,程式執行一下就變成2,另一個想要1就不可能。
class MyCounter {
private static int counter = 0;
public static int getCount() {
return counter++;
}
}
所以要改成同步方式(synchronized),這樣就算Thread-safe。
class MyCounter {
private static int counter = 0;
public static synchronized int getCount() {
return counter++;
}
}
Dispatcher
Servlet Container 收到HTTP Request後,Context提供分配機制,轉到某個Servlet去處理這個Request。
看個程式。
public class Dispatcher extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher rd = null;
System.out.println("In the servlet. . .");
//找ServletContext
ServletContext sc = getServletConfig().getServletContext();
//dispatcher 機制
switch(evaluate){
//轉到Servlet1
case(0): rd = sc.getRequestDispatcher("/Servlet1");
rd.forward(request, response);
break;
//轉到Servler2
case(1): rd = sc.getRequestDispatcher("/Servlet2");
rd.forward(request, response);
break;
}
}
@Override
public String getServletInfo() {
return "Short description";
}
}
Non-Blocking IO
這是 Sevlet3.1的新規格,處理ServletHTTPRequest大資料時,利用 AsyncServlet 可延遲回應Response。
@WebServlet(urlPatterns={"/asyncioservlet"}, asyncSupported=true)
public class AsyncIOServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
//設定AsyncContext處理非同步請求
final AsyncContext acontext = request.startAsync();
final ServletInputStream input = request.getInputStream();
input.setReadListener(new ReadListener() {
byte buffer[] = new byte[4*1024];
StringBuilder sbuilder = new StringBuilder();
@Override
public void onDataAvailable() {
try {
do {
int length = input.read(buffer);
sbuilder.append(new String(buffer, 0, length));
} while(input.isReady());
} catch (IOException ex) { ... }
}
@Override
public void onAllDataRead() {
try {
//AsyncContext 處理Response
acontext.getResponse().getWriter().write("...the response...");
} catch (IOException ex) { ... }
//完成非同步的請求
acontext.complete();
}
@Override
public void onError(Throwable t) { ... }
});
}
}
參考資料
Day 3結束